package com.apes.framework.plugin.todo;

import com.alibaba.fastjson.annotation.JSONField;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.ApesBean;
import com.apes.framework.jpa.DefaultPersistListener;
import com.apes.framework.jpa.comment.Comment;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.jpa.tuple.date.DateTime;
import com.apes.framework.plugin.outbox.annotation.OutBoxExclude;
import com.apes.framework.plugin.soe.metadata.BusinessType;
import com.apes.framework.plugin.soe.store.database.service.BusinessTypeService;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.EventUtil;
import com.apes.framework.util.MapUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.SelectBeforeUpdate;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.persistence.*;
import java.util.Date;

@OutBoxExclude
@Getter
@Setter
@SelectBeforeUpdate
@DynamicInsert
@DynamicUpdate
@Entity
@EntityListeners(DefaultPersistListener.class)
@Table(name = TodoTask.CONST_TABLE_NAME, indexes = {
        @Index(columnList = "aggregate_type, aggregate_id"),
        @Index(columnList = "user_id"),
        @Index(columnList = "state_instance_id")
})
public class TodoTask implements ApesBean {
    public static final String CONST_TABLE_NAME = "todo_task";

    @Id
    @Column(name = "id", length = 32)
    @ApesGenerator(code = CONST_TABLE_NAME, name = "待办")
    @Comment("编号")
    private String id;

    @Column(name = "description")
    @Comment("任务描述")
    private String description;

    @Column(name = "tags")
    @Comment("标签（经办、督办）")
    private String tags;

    @Lob
    @Basic(fetch = FetchType.LAZY)
    @Column(name = "payload", columnDefinition = "CLOB")
    @Comment("消息体")
    private String payload;

    @Column(name = "aggregate_type")
    @Comment("聚合根类型")
    private String aggregateType;

    @Column(name = "aggregate_id", length = 64)
    @Comment("聚合根ID")
    private String aggregateId;

    @Column(name = "when_mvel")
    @Comment("事件条件")
    private String whenMvel;

    @Column(name = "state")
    @Comment("状态：0-未处理；1-已处理；2-已作废")
    private int state = 0;

    @Column(name = "expired", updatable = false)
    @Comment("过期时间")
    private Date expired;

    @Column(name = "user_id", length = 64)
    @Comment("待办候选人")
    private String userId;

    @Column(name = "state_instance_id", length = 64)
    @Comment("状态实例编号")
    private String fsmStateInstanceId;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @DateTime(GenerationTime.INSERT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "create_date", updatable = false)
    @Comment("创建时间")
    private Date createDate;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @DateTime
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "update_date", insertable = false)
    @Comment("修改日期")
    private Date updateDate;

    @JSONField(format = DateUtil.SHOW_DATETIME_MILLI_FORMAT)
    @DateTime
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "last_updated_stamp")
    @Comment("时间戳")
    private Date lastUpdatedStamp;

    @Column(name = "init_dept_id", length = 32)
    @Comment("发起部门")
    private String initDeptId;

    @Version
    @Column(name = "version", columnDefinition = "number(10) default 0")
    @Comment("版本号")
    private int version;  //JPA乐观锁

    public String formId() {
        String formId = (String) EventUtil.sendSynEvent(this, "event:todo.formId.get",
                MapUtil.mapper("aggregateType", aggregateType, "aggregateId", aggregateId,"fsmStateInstanceId",fsmStateInstanceId))
                .stream().filter(o -> !ObjectUtils.isEmpty(o)).findFirst().orElse(null);
        if (!StringUtils.isEmpty(formId)) {
            return formId;
        }
        BusinessType businessType = businessType();
        return businessType.getFormId();
    }

    public String aggregateTypeName() {
        BusinessType businessType = businessType();
        return businessType.getName();
    }

    @SneakyThrows
    private BusinessType businessType() {
        Class clazz = Class.forName(aggregateType);
        return SpringManager.getBean(BusinessTypeService.class).getBusinessTypeByCache(clazz.getSimpleName());
    }
}
